package com.gxy.learn.office.excel;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.StringJoiner;

/**
 *
 *
 * http://doc.jeecg.com/2044224
 *
 * @Description: 校验Excel中的空值
 * @author: gaoxueyong
 * @Date: 2022/9/7 15:46
 */
@Slf4j
public class VerifyExcelValUtil {
    /**
     * 校验Excel文件信息
     *
     * @param myfile       需要校验的文件 必须时xlsx格式的
     * @param startRow     开始校验的行数 如果为null 则默认从第一行开始
     * @param cellMaxIndex 需要校验的列的最大索引 比如一行有20列，需要校验从1~5列则cellMaxIndex = 5
     * @throws IOException
     */
    public static void verifyExcelVal(MultipartFile myfile, Integer startRow, Integer cellMaxIndex) {
        String errMsg;
        XSSFWorkbook workbook = null;
        try {
            workbook = new XSSFWorkbook(myfile.getInputStream());
        } catch (IOException e) {
            errMsg = "解析文件失败！";
            log.error(errMsg, e);
            throw new RuntimeException(errMsg);
        }
        XSSFRow row;
        XSSFSheet sheet;
        int lastCellNum;
        int isReadFirstRowVal = 0;
        if (startRow != null && startRow.intValue() > 1) {
            isReadFirstRowVal = startRow.intValue() - 1;
        }
        if (null == cellMaxIndex || cellMaxIndex < 0) {
            cellMaxIndex = 0;
        }
        String fileName = myfile.getOriginalFilename();
        for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
            sheet = workbook.getSheetAt(sheetIndex);
            int sheetIndexNo = sheetIndex + 1;
            for (int i = isReadFirstRowVal; i <= sheet.getLastRowNum(); i++) {
                row = sheet.getRow(i);
                int rowNo = i + 1;
                lastCellNum = row.getLastCellNum();
                if (null != cellMaxIndex && (lastCellNum + 1) >= cellMaxIndex) {
                    lastCellNum = cellMaxIndex;
                }
                for (int cellIndex = 0; cellIndex < lastCellNum; cellIndex++) {
                    if (StringUtils.isBlank(row.getCell(cellIndex).getStringCellValue())) {
                        errMsg = String.format("%s的第%d个表格中第%d行第%d列为空！", fileName, sheetIndexNo,
                                rowNo, (cellIndex + 1));
                        log.error(errMsg);

                    }
                }
            }
        }
    }

    /**
     * 校验读取到的Excel实体类中那些是空值
     * @param obj
     * @param sj
     */
    private void verifyNull(Object obj, StringJoiner sj) {
        int nullSzie = 0;
        for (Field field : obj.getClass().getDeclaredFields()) {
            //在Java中可以通过反射进行获取实体类中的字段值，当未设置Field的setAccessible方法为true时，会在调用的时候进行访问安全检查，
            // 会抛出IllegalAccessException异常
            field.setAccessible(true);
            try {
                if (field.isAnnotationPresent(Excel.class)){
                    Excel annotation = field.getAnnotation(Excel.class);
                    String annoName = annotation.name();
                    if(StringUtils.isBlank(annoName)){
                        continue;
                    }
//                以*号结尾的需要校验是否未null
                    if(!annoName.endsWith("*")){
                        continue;
                    }
                    //属性名称
//                    String name = field.getName();
                    //属性值
                    Object fileObject = field.get(obj);
                    if (fileObject instanceof String) {
                        if (StringUtils.isBlank((String) fileObject)) {
                            sj.add(String.format("%s为空", annoName));
                        }
                    } else if (null == fileObject) {
                        if (StringUtils.isBlank((String) fileObject)) {
                            sj.add(String.format("%s为空", annoName));
                        }
                    }
                }
            } catch (IllegalArgumentException e) {
                log.error("对象属性解析异常" ,e);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                log.error("对象属性解析异常",e);
            }
        }
    }
}
